﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Threading;
using System.Windows.Input;
using System.Collections.ObjectModel;
using JiveMessenger.Models;
using GalaSoft.MvvmLight.Command;
using System.Diagnostics;
using System.ComponentModel;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml;
using Windows.ApplicationModel;
using JiveMessenger.Utilities;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using System.Threading.Tasks;
using Windows.UI.Core;
using JiveMessenger.CustomEventArgs;
using Windows.UI.Input;
using Windows.UI.Xaml.Media.Imaging;
using System.IO;
using XamlAnimatedGif;
using Windows.UI.ViewManagement;
using GalaSoft.MvvmLight.Messaging;
using Windows.UI.Xaml.Media.Animation;


namespace JiveMessenger.CustomControls
{

    public partial class EmoticonControl : UserControl
    {
        private PointerEventHandler PointerPressedEventHandler,PointerReleasedEventHandler;
        private CancellationTokenSource _cancelHoldTokenSource = new CancellationTokenSource();
        private bool _isHolding { get; set; }

        public static readonly DependencyProperty AddEmoticonCommandProperty = DependencyProperty.Register("AddEmoticonCommand", typeof(ICommand), typeof(EmoticonControl), new PropertyMetadata(null));

        public ICommand AddEmoticonCommand
        {
            get { return (ICommand)GetValue(AddEmoticonCommandProperty); }
            set { SetValue(AddEmoticonCommandProperty, value); }
        }

        public static readonly DependencyProperty DeleteEmoticonCommandProperty = DependencyProperty.Register("DeleteEmoticonCommand", typeof(ICommand), typeof(EmoticonControl), new PropertyMetadata(null));

        public ICommand DeleteEmoticonCommand
        {
            get { return (ICommand)GetValue(DeleteEmoticonCommandProperty); }
            set { SetValue(DeleteEmoticonCommandProperty, value); }
        }


        public static readonly DependencyProperty SendMessageCommandProperty = DependencyProperty.Register("SendMessageCommand", typeof(ICommand), typeof(EmoticonControl), new PropertyMetadata(null));

        public ICommand SendMessageCommand
        {
            get { return (ICommand)GetValue(SendMessageCommandProperty); }
            set { SetValue(SendMessageCommandProperty, value); }
        }


        public static readonly DependencyProperty BackspaceCommandProperty = DependencyProperty.Register("BackspaceCommand", typeof(ICommand), typeof(EmoticonControl), new PropertyMetadata(null));

        public ICommand BackspaceCommand
        {
            get { return (ICommand)GetValue(BackspaceCommandProperty); }
            set { SetValue(BackspaceCommandProperty, value); }
        }

        public static readonly DependencyProperty InsertEmoticonCommandProperty = DependencyProperty.Register("InsertEmoticonCommand", typeof(ICommand), typeof(EmoticonControl), new PropertyMetadata(null));

        public ICommand InsertEmoticonCommand
        {
            get { return (ICommand)GetValue(InsertEmoticonCommandProperty); }
            set { SetValue(InsertEmoticonCommandProperty, value); }
        }

        public double EmoticonButtonWidth
        {
            get { return (double)GetValue(EmoticonButtonWidthProperty); }
            set { SetValue(EmoticonButtonWidthProperty, value); }
        }

        // Using a DependencyProperty as the backing store for EmoticonButtonWidth.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty EmoticonButtonWidthProperty =
            DependencyProperty.Register("EmoticonButtonWidth", typeof(double), typeof(EmoticonControl), new PropertyMetadata(50));




        public double EmoticonButtonHeight
        {
            get { return (double)GetValue(EmoticonButtonHeightProperty); }
            set { SetValue(EmoticonButtonHeightProperty, value); }
        }

        // Using a DependencyProperty as the backing store for EmoticonButtonHeight.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty EmoticonButtonHeightProperty =
            DependencyProperty.Register("EmoticonButtonHeight", typeof(double), typeof(EmoticonControl), new PropertyMetadata(50));




        public Style EmoticonButtonStyle
        {
            get { return (Style)GetValue(EmoticonButtonStyleProperty); }
            set { SetValue(EmoticonButtonStyleProperty, value); }
        }

        // Using a DependencyProperty as the backing store for EmoticonButtonStyle.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty EmoticonButtonStyleProperty =
            DependencyProperty.Register("EmoticonButtonStyle", typeof(Style), typeof(EmoticonControl), new PropertyMetadata(new Style(typeof(Button))));


        public ObservableCollection<IEmoticon> RecentlyUsedEmoticons
        {
            get { return (ObservableCollection<IEmoticon>)GetValue(RecentlyUsedEmoticonsProperty); }
            set { SetValue(RecentlyUsedEmoticonsProperty, value); }
        }

        // Using a DependencyProperty as the backing store for RecentlyUsedEmoticons.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty RecentlyUsedEmoticonsProperty =
            DependencyProperty.Register("RecentlyUsedEmoticons", typeof(ObservableCollection<IEmoticon>), typeof(EmoticonControl), new PropertyMetadata(null));


        public int EmoticonPivotIndex
        {
            get { return (int)GetValue(EmoticonPivotIndexProperty); }
            set { SetValue(EmoticonPivotIndexProperty, value); }
        }

        // Using a DependencyProperty as the backing store for EmoticonPivotIndex.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty EmoticonPivotIndexProperty =
            DependencyProperty.Register("EmoticonPivotIndex", typeof(int), typeof(EmoticonControl), new PropertyMetadata(0));





        public ObservableCollection<JiveCustomEmoticonModel> CustomEmoticons
        {
            get { return (ObservableCollection<JiveCustomEmoticonModel>)GetValue(CustomEmoticonsProperty); }
            set { SetValue(CustomEmoticonsProperty, value); }
        }

        // Using a DependencyProperty as the backing store for CustomEmoticons.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CustomEmoticonsProperty =
            DependencyProperty.Register("CustomEmoticons", typeof(ObservableCollection<JiveCustomEmoticonModel>), typeof(EmoticonControl), new PropertyMetadata(null));



        public ObservableCollection<JiveDefaultEmoticonModel> DefaultEmoticons
        {
            get { return (ObservableCollection<JiveDefaultEmoticonModel>)GetValue(DefaultEmoticonsProperty); }
            set
            {
                SetValue(DefaultEmoticonsProperty, value);
            }
        }

        // Using a DependencyProperty as the backing store for DefaultEmoticons.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DefaultEmoticonsProperty =
            DependencyProperty.Register("DefaultEmoticons", typeof(ObservableCollection<JiveDefaultEmoticonModel>), typeof(EmoticonControl), new PropertyMetadata(null));


        public EmoticonControl()
        {
            InitializeComponent();
            this.EmoticonGrid.DataContext = this;
            PointerPressedEventHandler = new PointerEventHandler(BackspaceButton_PointerPressed);
            PointerReleasedEventHandler = new PointerEventHandler(BackspaceButton_PointerReleased);

            //Messenger.Default.Register<NotificationMessage>(this, async msg =>
            //    {
            //        switch (msg.Notification)
            //        {
            //            case "UpdateCustomEmoticons":
            //                await Task.Delay(50);
            //                this.CustomEmoticonsItemControl.Update();
            //                break;
            //        }
            //    });

        }
        

        private void UserControl_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            this.BackspaceButton.AddHandler(Button.PointerPressedEvent, PointerPressedEventHandler, true);
            this.BackspaceButton.AddHandler(Button.PointerReleasedEvent, PointerReleasedEventHandler, true);
        }

        private void UserControl_Unloaded(object sender, RoutedEventArgs e)
        {
            this.BackspaceButton.RemoveHandler(Button.PointerPressedEvent, PointerPressedEventHandler);
            this.BackspaceButton.RemoveHandler(Button.PointerReleasedEvent, PointerReleasedEventHandler);
        }

        //private void BackspaceButton_Hold(object sender, Windows.UI.Xaml.Input.HoldingRoutedEventArgs e)
        //{
        //    switch (e.HoldingState)
        //    {
        //        case Windows.UI.Input.HoldingState.Started:
        //            _isHolding = true;
        //            Debug.WriteLine("holding started");
        //            Task.Factory.StartNew(async () =>
        //                {
        //                    DateTime start = DateTime.UtcNow;
        //                    while (_isHolding)
        //                    {
        //                        await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        //                         {
        //                             BackspaceCommand.Execute(null);
        //                         });
        //                        int sleeptime = 100;
        //                        if (DateTime.UtcNow.Subtract(start).TotalSeconds >= 1.5)
        //                            sleeptime = 50;

        //                        await Task.Delay(TimeSpan.FromMilliseconds(sleeptime));
        //                    }
        //                });
        //            break;
        //        case Windows.UI.Input.HoldingState.Canceled:
        //        case Windows.UI.Input.HoldingState.Completed:
        //            _isHolding = false;
        //            Debug.WriteLine("holding ended");
        //            break;

        //    }
        //}





        private void BackspaceButton_Tapped(object sender, TappedRoutedEventArgs e)
        {
            if (BackspaceCommand != null)
                BackspaceCommand.Execute(null);

        }

        private void SendButton_Tapped(object sender, TappedRoutedEventArgs e)
        {
            if (SendMessageCommand != null)
                SendMessageCommand.Execute(null);
        }


        private bool _emoticonContextMenuIsOpen;
        private void Border_PointerExited(object sender, PointerRoutedEventArgs e)
        {
            if (_emoticonContextMenuIsOpen)
                return;
            Border b = sender as Border;
            IEmoticon model = b.DataContext as IEmoticon;

            if (_emoticonContextMenuIsOpen)
                return;

            this.InsertEmoticonCommand.Execute(model);
        }

        //private void Image_Loaded(object sender, RoutedEventArgs e)
        //{
        //    return;
        //    Image img = sender as Image;
        //    if (!(img.Source is BitmapImage))
        //        return;
        //    Uri uriSource = ((BitmapImage)img.Source).UriSource;
        //    string ext = Path.GetExtension(uriSource.AbsolutePath);
        //    if (ext == ".gif")
        //    {
        //        XamlAnimatedGif.AnimationBehavior.SetAutoStart(img, true);
        //        XamlAnimatedGif.AnimationBehavior.SetSourceUri(img, new Uri(uriSource.AbsoluteUri.Replace(":/", ":///")));//"ms-appx://" + uriSource.AbsolutePath));//new Uri(src.UriSource.AbsoluteUri));
        //    }
        //}
        //int _customImagesLoaded = 0;
        //private void Image_ImageOpened(object sender, RoutedEventArgs e)
        //{
        //    Image img = (Image)sender;
        //    BitmapImage imgSource = (BitmapImage)img.Source;
        //    var panel = this.CustomEmoticonsItemControl.ItemsPanelRoot as VariableSizedWrapGrid;
        //    if (panel == null)
        //        return;
        //    int maxRowSpan = 2;
        //    int maxColSpan = 3;
        //    if (img.DataContext is JiveCustomEmoticonModel)
        //    {
        //        JiveCustomEmoticonModel emoticon = (JiveCustomEmoticonModel)img.DataContext;
        //        emoticon.ColSpan = (int)Math.Round((double)(imgSource.PixelWidth / panel.ItemHeight));
        //        emoticon.RowSpan = (int)Math.Round((double)(imgSource.PixelHeight / panel.ItemHeight));

        //        if (emoticon.ColSpan > maxColSpan)
        //        {

        //            emoticon.RowSpan = Convert.ToInt32(Math.Round(emoticon.RowSpan * ((double)maxColSpan / (double)emoticon.ColSpan)));
        //            emoticon.ColSpan = maxColSpan;
        //        }
        //        if (emoticon.RowSpan > maxRowSpan)
        //        {
        //            emoticon.ColSpan = (int)Math.Round((double)emoticon.ColSpan * (maxRowSpan / emoticon.RowSpan));
        //            emoticon.RowSpan = maxRowSpan;
        //        }

        //    }
        //    _customImagesLoaded++;

        //    if (_customImagesLoaded >= this.CustomEmoticonsItemControl.Items.Count)
        //    {
        //        this.CustomEmoticonsItemControl.Update();
        //    }
        //}


        private void FrameworkElement_Holding(object sender, HoldingRoutedEventArgs e)
        {
            _emoticonContextMenuIsOpen = true;
            e.Handled = true;
            FrameworkElement selectedItem = sender as FrameworkElement;
            var flyOut = Flyout.GetAttachedFlyout(selectedItem);
            flyOut.Closed += flyOut_Closed;
            flyOut.ShowAt(selectedItem);
        }

        void flyOut_Closed(object sender, object e)
        {
            _emoticonContextMenuIsOpen = false;
        }


        private void DeleteMenuFlyoutItem_Click(object sender, RoutedEventArgs e)
        {
            MenuFlyoutItem item = (MenuFlyoutItem)sender;
            var emoticon = item.DataContext as JiveCustomEmoticonModel;
            DeleteEmoticonCommand.Execute(emoticon);
        }

        private void AddEmoticonButton_Tapped(object sender, TappedRoutedEventArgs e)
        {
            if (this.AddEmoticonCommand != null)
                this.AddEmoticonCommand.Execute(null);
        }

        private void BackspaceButton_PointerPressed(object sender, PointerRoutedEventArgs e)
        {
            _cancelHoldTokenSource = new CancellationTokenSource();
            Task.Run(async () =>
                {
                    await Task.Delay(500);
                    if (_cancelHoldTokenSource.IsCancellationRequested)
                        return;
                    DateTime start = DateTime.UtcNow;
                    while (true)
                    {
                        if (_cancelHoldTokenSource.IsCancellationRequested)
                            break;
                        await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                        {
                            BackspaceCommand.Execute(null);
                        });
                        int sleeptime = 100;
                        if (DateTime.UtcNow.Subtract(start).TotalSeconds >= 1.5)
                            sleeptime = 50;

                        await Task.Delay(TimeSpan.FromMilliseconds(sleeptime));
                    }

                }, _cancelHoldTokenSource.Token);
        }

        private void BackspaceButton_PointerReleased(object sender, PointerRoutedEventArgs e)
        {
            _cancelHoldTokenSource.Cancel();
        }






    }
}
